10 REM *** (FFT10-01.BAS) FFT ***

12 CLS : COLOR 15, 1: PRINT : PRINT "INPUT NUMBER OF DATA POINTS AS 2^N"

14 INPUT "N = "; N

16 Q = 2 ^ N: Q1 = Q - 1: N1 = N - 1

18 Q2 = Q / 2: Q3 = Q2 - 1: Q4 = Q / 4: Q5 = Q4 - 1: Q8 = Q / 8

20 DIM C(2, Q), S(2, Q), KC(Q), KS(Q)

22 PI = 3.141592653589793#: P2 = 2 * PI: K1 = P2 / Q

24 '  **** TWIDDLE FACTOR TABLE GENERATION ****

26 FOR I = 0 TO Q: KC(I) = COS(K1 * I): KS(I) = SIN(K1 * I)

28 IF ABS(KC(I)) < .0000005 THEN KC(I) = 0 ' CLEAN UP TABLES

30 IF ABS(KS(I)) < .0000005 THEN KS(I) = 0

32 NEXT I

34 FOR I = 1 TO Q1: INDX = 0

36 FOR J = 0 TO N1

38 IF I AND 2 ^ J THEN INDX = INDX + 2 ^ (N1 - J)

40 NEXT J

42 IF INDX > I THEN SWAP KC(I), KC(INDX): SWAP KS(I), KS(INDX)

44 NEXT I

46 CLS

50 PRINT SPC(30); "MAIN MENU": PRINT : PRINT

60 PRINT SPC(5); "1 = FUNCTION MENU": PRINT

62 PRINT SPC(5); "2 = FORWARD TRANSFORM": PRINT

64 PRINT SPC(5); "3 = INVERSE TRANSFORM": PRINT

66 PRINT SPC(5); "4 = INNER PRODUCT OF FUNCTIONS": PRINT

68 PRINT SPC(5); "5 = EXIT": PRINT

70 PRINT SPC(10); "MAKE SELECTION :";

80 A$ = INKEY$: IF A$ = "" THEN 80

90 A = VAL(A$): ON A GOSUB 600, 500, 700, 800, 990

95 GOTO 40

100 REM *** FFT ***

102 CLS : PRINT "  FREQ    F(COS)        F(SIN)        ";

104 PRINT "FREQ     F(COS)        F(SIN)": PRINT : PRINT

106 T9 = TIMER

110 REM *** FFT ROUTINE ***

112 FOR M = 0 TO N1: QT = 2 ^ (N - M): QT1 = QT - 1

114 QT2 = QT / 2: QT3 = QT2 - 1: KT = 0

116 REM *** UNIVERSAL BUTTERFLY ***

118 FOR J = 0 TO Q1 STEP QT: KT2 = KT + 1

120 FOR I = 0 TO QT3: J1 = I + J: K = J1 + QT2

122 CTEMP = (C(T0, J1) + C(T0, K) * KC(KT) - K6 * S(T0, K) * KS(KT)) / SK1

124 STEMP = (S(T0, J1) + K6 * C(T0, K) * KS(KT) + S(T0, K) * KC(KT)) / SK1

126 CTEMP2 = (C(T0, J1) + C(T0, K) * KC(KT2) - K6 * S(T0, K) * KS(KT2)) / SK1

128 S(T0, K) = (S(T0, J1) + K6 * C(T0, K) * KS(KT2) + S(T0, K) * KC(KT2)) / SK1

130 C(T0, K) = CTEMP2: C(T0, J1) = CTEMP: S(T0, J1) = STEMP

132 NEXT I

134 KT = KT + 2: NEXT J

136 NEXT M

140 ' ***  BIT REVERSAL FOR FINAL DATA ***

142 FOR I = 1 TO Q1: INDX = 0

144 FOR J = 0 TO N1

146 IF I AND 2 ^ J THEN INDX = INDX + 2 ^ (N1 - J)

148 NEXT J

150 IF INDX > I THEN SWAP C(T0, I), C(T0, INDX): SWAP S(T0, I), S(T0, INDX)

152 NEXT I



200 T9 = TIMER - T9

210 GOSUB 300

220 PRINT : PRINT "TIME ="; T9

225 PRINT : PRINT : INPUT "C/R TO CONTINUE:"; A$

230 RETURN

300 ' **** PRINT COMPLEX QUANTITY DATA ****

302 FOR Z = 0 TO Q3

304 GOSUB 310

306 NEXT Z

308 RETURN

310 PRINT USING "####"; Z; : PRINT "   ";

312 PRINT USING "+##.######"; C(T0, Z); : PRINT "    ";

314 PRINT USING "+##.######"; S(T0, Z); : PRINT "      ";

320 PRINT USING "####"; Z + Q2; : PRINT "   ";

322 PRINT USING "+##.######"; C(T0, Z + Q2); : PRINT "    ";

324 PRINT USING "+##.######"; S(T0, Z + Q2)

330 RETURN



400 REM GENERATE TRIANGLE WAVE

402 T8 = TIMER + 1

408 IF Q / 2 > 1024 THEN QT = 1024 ELSE QT = Q / 2

410 FOR I = 0 TO Q: C(T0, I) = 0: S(T0, I) = 0

420 FOR J = 1 TO QT STEP 2: C(T0, I) = C(T0, I) + COS(K1 * J * I) / (J * J): NEXT

422 IF TIMER > T8 THEN GOSUB 450

430 NEXT I

440 RETURN

450 REM *** BLINK WAIT MESSAGE ***

452 DISFLG = 1 - DISFLG

454 IF DISFLG = 1 THEN CLS : GOTO 460

456 LOCATE 10, 22

458 PRINT "PREPARING DATA - PLEASE WAIT"

460 T8 = TIMER + 1: RETURN



500 ' **** FORWARD TRANSFORM ****

502 SK1 = 2: K6 = 1

506 GOSUB 100

508 RETURN



600 REM * FUNCTION MENU *

602 CLS : PRINT : PRINT

604 PRINT SPC(20); "FUNCTION MENU": PRINT : PRINT

606 PRINT "1 = MANUAL INPUT FUNCTION 1": PRINT

608 PRINT "2 = MANUAL INPUT FUNCTION 2": PRINT

610 PRINT "3 = GENERATE Q/2 TRIANGLE WAVE": PRINT : PRINT

612 PRINT "MAKE SELECTION  (0 = EXIT):";

614 A$ = INKEY$: IF A$ = "" THEN 614

615 IF ASC(A$) < 48 OR ASC(A$) > 51 THEN GOSUB 690: GOTO 612

616 A = VAL(A$): IF A = 0 THEN RETURN

618 ON A GOTO 640, 642, 630

630 T0 = 1: GOSUB 400

631 CLS : PRINT "  TIME   AMPLITUDE     NOT USED       ";

632 PRINT "TIME    AMPLITUDE     NOT USED": PRINT : PRINT

633 GOSUB 300

634 PRINT : INPUT "DATA READY - C/R TO CONTINUE"; A$

636 RETURN

' ********  MANUAL INPUT  *********

640 T0 = 1: GOTO 644

642 T0 = 2

644 FOR I = 0 TO Q1: C(T0, I) = 0: S(T0, I) = 0: NEXT I

646 CLS : PRINT SPC(15); "- INPUT DATA FUNCTION "; T0; " (THERE ARE "; Q; " DATA POINTS) -"

648 I = 0: PRINT : PRINT

650 PRINT SPC(5); "DATA POINT "; I; " (9999 TO EXIT - 9998 TO BACK UP)";

652 INPUT C(T0, I)

654 IF C(T0, I) = 9999 THEN C(T0, I) = 0: I = Q: GOTO 660

656 IF C(T0, I) = 9998 THEN C(T0, I) = 0: I = I - 1: GOTO 650

658 I = I + 1: IF I < Q THEN 650

660 GOTO 631

662 RETURN

690 PRINT "INVALID SELECTION": RETURN



700 REM *** INVERSE TRANSFORM ***

710 SK1 = 1: K6 = -1

712 CLS : PRINT "  TIME   AMPLITUDE     NOT USED       ";

714 PRINT "TIME   AMPLITUDE     NOT USED": PRINT : PRINT

720 GOSUB 106

730 RETURN

800 ' **** INNER PRODUCT OF FUNCTIONS ****

802 CLS : PRINT "PRODUCT IN FUNCTION 1"

804 T0 = 1

806 FOR I = 0 TO Q1

808 CTEMP = (C(1, I) * C(2, I)) - (S(1, I) * S(2, I))

810 S(1, I) = (C(1, I) * S(2, I)) + (C(2, I) * S(1, I))

812 C(1, I) = CTEMP

814 NEXT I

816 GOSUB 300

818 INPUT "C/R TO CONTINUE"; A$

820 RETURN



990 END: STOP



